package ebj.common.annotation.demo_data_provider_manager.anno;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.velocity.VelocityContext;
import org.reflections.ReflectionUtils;
import org.reflections.Reflections;

import com.google.common.base.Strings;
import com.google.common.collect.Ordering;

import ebj.common.annotation.demo_data_provider_manager.data_provider.DataProvider;

/***********注解处理器***************/

public class AnnoProcessor {
    public static void getProviderInfo(Class<?> clazz){
        
        /*
        String strFruitName=" 水果名称：";
        String strFruitColor=" 水果颜色：";
        String strFruitProvicer="供应商信息：";
        
        Field[] fields = clazz.getDeclaredFields();
        
        for(Field field :fields){
            if(field.isAnnotationPresent(FruitName.class)){
                FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);
                strFruitName=strFruitName+fruitName.value();
                System.out.println(strFruitName);
            }
            else if(field.isAnnotationPresent(FruitColor.class)){
                FruitColor fruitColor= (FruitColor) field.getAnnotation(FruitColor.class);
                strFruitColor=strFruitColor+fruitColor.fruitColor().toString();
                System.out.println(strFruitColor);
            }
            else if(field.isAnnotationPresent(FruitProvider.class)){
                FruitProvider fruitProvider= (FruitProvider) field.getAnnotation(FruitProvider.class);
                strFruitProvicer=" 供应商编号："+fruitProvider.id()+"; 供应商名称："+fruitProvider.name()+"; 供应商地址："+fruitProvider.address();
                System.out.println(strFruitProvicer);
            }
        }
        */
    }
    
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static Map<String, Class<? extends DataProvider>> getAllDataProviders(String... basePackages) {
        Map<String, Class<? extends DataProvider>> providers = new HashMap<String, Class<? extends DataProvider>>();
        for (String string : basePackages) {
            if (!Strings.isNullOrEmpty(string)) {
                Set<Class<?>> classSet = new Reflections(string).getTypesAnnotatedWith(ProviderName.class);
                for (Class clasz : classSet) {
                    if (!clasz.isAssignableFrom(DataProvider.class)) {
                        providers.put(((ProviderName) clasz.getAnnotation(ProviderName.class)).value().toLowerCase(), clasz);
                    } else {
                        String msg = "请确认你的自定义DataProvider已继承自[" + DataProvider.class.getName() + "].";
                        System.err.println(msg);
                    }
                }
            }else {
                System.err.println("No package defined.");
            }
        }
        return providers;
    }
    
    public static List<Map<String, String>> geAllQueryParammeters(DataProvider dataProvider) throws InstantiationException, IllegalAccessException {
        List<Map<String, String>> params = new ArrayList<Map<String,String>>();
        @SuppressWarnings("unchecked")
        Set<Field> fieldSet = ReflectionUtils.getAllFields(dataProvider.getClass(), ReflectionUtils.withAnnotation(QueryParameter.class));
        List<Field> fieldList = fieldOrdering.sortedCopy(fieldSet);
        for (Field field : fieldList) {
            field.setAccessible(true);
            QueryParameter providerAttribute = field.getAnnotation(QueryParameter.class);
            Map<String, String> param = new HashMap<>();
            param.put("label", providerAttribute.name());
            param.put("type", providerAttribute.type().toString());
            param.put("name", (String) field.get(dataProvider));
            params.add(param);
        }
        return params;
    }
    public static List<Map<String, String>> geAllDataProviderAttributes(DataProvider dataProvider) throws InstantiationException, IllegalAccessException {
        List<Map<String, String>> params = new ArrayList<Map<String,String>>();
        @SuppressWarnings("unchecked")
        Set<Field> fieldSet = ReflectionUtils.getAllFields(dataProvider.getClass(), ReflectionUtils.withAnnotation(ProviderAttribute.class));
        List<Field> fieldList = fieldOrdering.sortedCopy(fieldSet);
        for (Field field : fieldList) {
            field.setAccessible(true);
            ProviderAttribute providerAttribute = field.getAnnotation(ProviderAttribute.class);
            Map<String, String> param = new HashMap<>();
            param.put("label", providerAttribute.name());
            param.put("type", providerAttribute.type().toString());
            param.put("name", (String) field.get(dataProvider));
            params.add(param);
        }
        return params;
    }
    
    private static Ordering<Field> fieldOrdering = Ordering.from(new Comparator<Field>() {
        @Override
        public int compare(Field o1, Field o2) {
            return Integer.compare(getOrder(o1), getOrder(o2));
        }

        private int getOrder(Field field) {
            field.setAccessible(true);
            ProviderAttribute datasourceParameter = field.getAnnotation(ProviderAttribute.class);
            if (datasourceParameter != null) {
                return datasourceParameter.order();
            }
            QueryParameter queryParameter = field.getAnnotation(QueryParameter.class);
            if (queryParameter != null) {
                return queryParameter.order();
            }
            return 0;
        }
    });
}